﻿' Copyright (c) Microsoft Open Technologies, Inc.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

Imports System.IO
Imports System.Console

''' <summary>
''' Contains the startup code, command line argument processing, and driving the execution of the tool.
''' </summary>
Module Program

    Function Main(args As String()) As Integer

        Const exitWithErrors = 1,
              exitWithoutErrors = 0

        Try

            Dim paths = From arg In args Where Not arg.StartsWith("/")

            Dim switches = From arg In args Where arg.StartsWith("/")

            ' Write usage.
            If switches.Contains("/?") OrElse paths.Count <> 2 OrElse switches.Count > 1 Then
                WriteLine("VBSyntaxGenerator.exe input output [/source] [/test]")
                WriteLine("  /source        Generates syntax model source code.")
                WriteLine("  /test          Generates syntax model unit tests.")
                WriteLine("  /gettext       Generates GetText method only.")

                Return exitWithErrors
            End If

            Dim inputFile = paths(0)
            Dim outputFile = paths(1)

            If Not File.Exists(inputFile) Then
                WriteLine("Input file not found - ""{0}""", inputFile)

                Return exitWithErrors
            End If

            Dim definition = ReadDefinition(inputFile)
            Dim outputKind = If(switches.Any(), switches(0).ToLowerInvariant(), Nothing)
            WriteOutput(outputFile, definition, outputKind)

            Return exitWithoutErrors
        Catch ex As Exception
            WriteLine("FATAL ERROR: {0}", ex.Message)
            WriteLine(ex.StackTrace)

            Return exitWithErrors
        End Try

    End Function

    Function ReadDefinition(inputFile As String) As ParseTree
        Dim definition = ReadTheTree(inputFile)

        ValidateTree(definition)

        Return definition
    End Function

    Sub WriteOutput(outputFile As String, definition As ParseTree, outputKind As String)

        Using output As New StreamWriter(outputFile)
            output.WriteLine("' Definition of syntax model.")
            output.WriteLine("' Generated by a tool on {0:g}", Date.Now)
            output.WriteLine("' DO NOT HAND EDIT")


            Select Case outputKind
                Case "/test"
                    output.WriteLine()
                    output.WriteLine("Imports System.Collections.Generic")
                    output.WriteLine("Imports System.Collections.Immutable")
                    output.WriteLine("Imports System.Runtime.CompilerServices")
                    output.WriteLine("Imports Microsoft.CodeAnalysis.VisualBasic.Syntax")
                    output.WriteLine("Imports Roslyn.Utilities")
                    output.WriteLine("Imports Xunit")

                    Dim testWriter As New TestWriter(definition)
                    testWriter.WriteTestCode(output)

                Case "/gettext"
                    Dim syntaxFactsWriter As New SyntaxFactsWriter(definition)
                    syntaxFactsWriter.GenerateGetText(output)

                Case Else
                    output.WriteLine()
                    output.WriteLine("Imports System.Collections.Generic")
                    output.WriteLine("Imports System.Collections.Immutable")
                    output.WriteLine("Imports System.Runtime.CompilerServices")
                    output.WriteLine("Imports Microsoft.CodeAnalysis.VisualBasic.Syntax")
                    output.WriteLine("Imports Roslyn.Utilities")

                    Dim redNodeWriter As New RedNodeWriter(definition)
                    redNodeWriter.WriteTreeAsCode(output)

                    Dim greenNodeWriter As New GreenNodeWriter(definition)
                    greenNodeWriter.WriteTreeAsCode(output)

                    Dim redFactoryWriter As New RedNodeFactoryWriter(definition)
                    redFactoryWriter.WriteFactories(output)

                    Dim greenFactoryWriter As New GreenNodeFactoryWriter(definition)
                    greenFactoryWriter.WriteFactories(output)

                    Dim syntaxFactsWriter As New SyntaxFactsWriter(definition)
                    syntaxFactsWriter.GenerateFile(output)

            End Select

            WriteLine("{0} node structures, {1} enumerations, {2} node kinds", definition.NodeStructures.Count, definition.Enumerations.Count, definition.NodeKinds.Count)
        End Using

    End Sub

End Module
